/*
 * sci.c
 *
 *      Author: Mario
 */

#include <stdio.h>
#include <stdlib.h>
#include "DSP28x_Project.h"
#include "sci.h"

struct SCI_MESSAGE * SCI_ll_front;

// Test 1,SCIA  DLB, 8-bit word, baud rate 0x000F, default, 1 STOP bit, no parity
void scia_init()
{
    // Note: Clocks were turned on to the SCIA peripheral
    // in the InitSysCtrl() function

 	SciaRegs.SCICCR.all				=	0x0007;		// 1 stop bit,  No loopback
 													// No parity, 8 char bits,
 													// async mode, idle-line protocol
	SciaRegs.SCICTL1.all			=	0x0003;		// enable TX, RX, internal SCICLK,
													// Disable RX ERR, SLEEP, TXWAKE
	SciaRegs.SCICTL2.bit.TXINTENA	=	0;
	SciaRegs.SCICTL2.bit.RXBKINTENA	=	0;

	SciaRegs.SCIHBAUD				=	0x0000;  	// 9600 baud @LSPCLK = 15MHz (60 MHz SYSCLK).
    SciaRegs.SCILBAUD				=	0x00C2;

	SciaRegs.SCICTL1.all			=	0x0023;		// Relinquish SCI from Reset
}

// Transmit a character from the SCI
void scia_xmit(int a)
{
    while (SciaRegs.SCICTL2.bit.TXRDY != 1) {}
    SciaRegs.SCITXBUF = a;

}

void scia_msg(char * msg, int length)//byte * msg, int numBytes)
{
	int i;
	byte * packet = api_packetize(msg, length);

	for(i = 0; packet[i] != 0x51; i++)
		scia_xmit(packet[i]);

    free(packet);
}

void scia_rx(){
  scia_clear_read();

  if(SCI_ll_front == NULL) {
	   SCI_ll_front = (struct SCI_MESSAGE* )malloc(sizeof(struct SCI_MESSAGE));
  }

  struct SCI_MESSAGE * SCI_msg_ptr  = SCI_ll_front;
      
   while(SCI_msg_ptr->next != NULL) {
	   SCI_msg_ptr = SCI_msg_ptr->next;
   }
	
   SCI_msg_ptr->next = (struct SCI_MESSAGE* ) malloc(sizeof(struct SCI_MESSAGE));
   SCI_msg_ptr->message = SciaRegs.SCIRXBUF.bit.RXDT;
   
}

byte * api_packetize(byte data[], int dataLength) {
	Uint16 i,j;
	Uint16 numEscapes = 0;
	Uint16 length, lengthWithEscs;
	byte checkSum = 0;

	//ESCAPE (FROM BYTE 1)  0x7E, 0x7D, 0x11, 0x13 -> 0x7D , (oldvalue)xor(0x20)
	byte msg[] = {	0x7E, //DELIMITER		0
					0x00, //LENGTH			1
					0x00, //LENGTH			2
					0x01, //API ID			3
					0x01, //FRAME ID		4
					0x00, //ADDRESS			5
					0x13, //ADDRESS			6
					0xA2, //ADDRESS			7
					0x00, //ADDRESS			8
					0x40, //ADDRESS			9
					0x9F, //ADDRESS			10
					0x0E, //ADDRESS			11
					0x2A, //ADDRESS			12
					0x33, //NETWORK			13
					0x32, //NETWORK			14
					0x00, //ZEROS 			15
					0x00  //ZEROS			16
//					0x41, //DATA			17
//					0x41, //DATA			18
//					0x41, //DATA			19
//					0x09,	//CHECK SUM		20
//					0xF1  //MAKESHIFT TERMINATING CHAR
	};

	// calculate number of escapes in msg and data

	byte * msgPointer = (byte *)malloc((17 + dataLength + 1 + 1) * sizeof(byte));
	byte * msgPtrEsc = NULL;
	byte * lengthH = &msgPointer[1];
	byte * lengthL = &msgPointer[2];
	byte * chkSumByte = &msgPointer[dataLength - 2];
	byte * termCharByte = &msgPointer[dataLength - 1];

	// enter packet header
	for(i = 0; i < 17; i++) {
		msgPointer[i] = msg[i];
		if((i != 0) && isEsc(msg[i]))
			numEscapes++;
		checkSum += msg[i];
	}

	// enter packet data
	for(i = 0; i < dataLength; i++) {
		msgPointer[17+i] = data[i];
		if(isEsc(data[i]))
			numEscapes++;
		checkSum += data[i];
	}

	// enter checksum and terminating character
	*chkSumByte = 0xFF - (byte)(checkSum & 0xFF);
	if(isEsc(*chkSumByte)) numEscapes++;
	*termCharByte = 0xF1;

	// calculate packet length
	// <<<why minus 3?>>>
	length = (17 + dataLength - 3);
	*lengthH = (byte)((length && 0xFF00) >> 8);
	*lengthL = (byte)(length && 0x00FF);

	if(isEsc(*lengthH)) numEscapes++;
	if(isEsc(*lengthL)) numEscapes++;

	// create packet with proper escape characters
	lengthWithEscs = 17 + dataLength + 1 + 1 + numEscapes;
	msgPtrEsc = (byte *)malloc(lengthWithEscs * sizeof(byte));
	msgPtrEsc[0] = msgPointer[0];

	for(i = 1, j = 1; i < 17 + dataLength + 1 + 1; i++, j++) {
		if(isEsc(msgPointer[i])) {
			msgPtrEsc[j] = 0x7D;
			msgPtrEsc[++j] = msgPointer[i] ^ 0x20;
		} else {
			msgPtrEsc[j] = msgPointer[i];
		}
	}

	free(msgPointer);
	return msgPtrEsc;
}

bool isEsc(byte x) {
	return (x == 0x7E || x == 0x7D || x == 0x11 || x == 0x13);
}


void scia_clear_read() {
   struct SCI_MESSAGE * SCI_msg_ptr;

   while(SCI_ll_front != NULL && SCI_ll_front->read == true) {
	   SCI_msg_ptr = SCI_ll_front;
	   SCI_ll_front = SCI_ll_front->next;
	   free(SCI_msg_ptr);
   }
   return;
}
